package com.huayi.datagovernance.utils.string;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import org.junit.Test;

import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;

/**
 * 字符串工具-StrUtil
 * 这个工具的用处类似于Apache Commons Lang中的StringUtil，之所以使用StrUtil而不是使用StringUtil是因为前者更短，
 * 而且Str这个简写我想已经深入人心了，大家都知道是字符串的意思。常用的方法例如isBlank、isNotBlank、isEmpty、isNotEmpty这些我就不做介绍了，
 * 判断字符串是否为空，下面我说几个比较好用的功能。
 * @author wuch
 * @version 1.0
 * @date 2021/4/19 9:24
 */
public class StrUtilDemo {
    //  字符串工具  定义的一些常量
    // 像点、空串、换行符等等，还有HTML中的一些转义字符
    static int INDEX_NOT_FOUND = StrUtil.INDEX_NOT_FOUND; //-1 指定下标的字符串未找到
    static char C_SPACE = StrUtil.C_SPACE; //" " 空格符 字符类型
    static String SPACE = StrUtil.SPACE; // 空格符 字符串类型
    static String TAB = StrUtil.SPACE; //"\t" 缩进
    static String COMMA = StrUtil.COMMA; //"," 英文逗号
    static String DOT = StrUtil.DOT; //"." 英文句号
    static String DOUBLE_DOT = StrUtil.DOUBLE_DOT; //".." 双英文逗号
    static String SLASH = StrUtil.SLASH; //"/" 正斜杠
    static String BACKSLASH = StrUtil.SLASH; //"\" 反斜杠
    static String EMPTY = StrUtil.EMPTY; //"" 空字符串
    static String NULL = StrUtil.NULL; //"null" null字符串
    static String CR = StrUtil.CR; //"\r" 回车，回到行首
    static String LF = StrUtil.LF; //"\n" 换行
    static String CRLF = StrUtil.CRLF; //"\r\n" 回车并换行
    static String UNDERLINE = StrUtil.UNDERLINE; //"_" 下划线
    static String DASHED = StrUtil.DASHED; //"_" 破折号
    static String DELIM_START = StrUtil.DELIM_START; //"{" 大括号-左
    static String DELIM_END = StrUtil.DELIM_END; //"}" 大括号-右
    static String BRACKET_START = StrUtil.BRACKET_START; //"[" 中括号-左
    static String BRACKET_END = StrUtil.BRACKET_END; //"]" 中括号-右
    static String COLON = StrUtil.COLON; //":" 冒号
    static String HTML_NBSP = StrUtil.HTML_NBSP; //"" 不断开空格 html转义字符
    static String HTML_AMP = StrUtil.HTML_AMP; //"&" & html转义字符
    static String HTML_QUOTE = StrUtil.HTML_QUOTE; //"'" 单引号 html转义字符
    static String HTML_APOS = StrUtil.HTML_APOS; //""" 双引号 html转义字符
    static String HTML_LT = StrUtil.HTML_LT; //"<" 小于 html转义字符
    static String HTML_GT = StrUtil.HTML_GT; //":> 大于 html转义字符
    static String EMPTY_JSON = StrUtil.EMPTY_JSON; //"{}" 空的JSON字符串




    /**
     * 判空
     */
    @Test
    public void test1(){
        //这两个方法的区别是hasEmpty只判断是否为null或者空字符串（""），hasBlank则会把不可见字符也算做空，isEmpty和isBlank同理。
        String nullstr = "";
        String noSeestr = " ";
        Console.log(StrUtil.hasEmpty(nullstr));
        Console.log(StrUtil.isEmpty(noSeestr));
        Console.log(StrUtil.hasBlank(nullstr));
        Console.log(StrUtil.isBlank(noSeestr));

        //判断Object 是否为字符串且是否为空
        Object obj = "23";
        boolean blankIfStr = StrUtil.isBlankIfStr(obj);
        Console.log(blankIfStr);

        boolean emptyIfStr = StrUtil.isEmptyIfStr(obj);
        Console.log(emptyIfStr);

    }

    /**
     *  removePrefix、removeSuffix方法
     * 这两个是去掉字符串的前缀后缀的，例如去个文件名的扩展名啥。
     * 还有忽略大小写的removePrefixIgnoreCase和removeSuffixIgnoreCase都比较实用。
     */
    @Test
    public void test2(){

        Console.log(StrUtil.removeSuffix("pretty_girl.jpg", ".jpg")); //fileName -> pretty_girl
        Console.log(StrUtil.removePrefixIgnoreCase("pretty_girl.jpg", "PRETTY")); //fileName -> _girl.jpg
    }

    /**
     * sub方法
     * 不得不提一下这个方法，有人说String有了subString你还写它干啥，我想说subString方法越界啥的都会报异常，你还得自己判断，难受死了，
     * 我把各种情况判断都加进来了，而且index的位置还支持负数哦，-1表示最后一个字符（这个思想来自于Python，如果学过Python的应该会很喜欢的），
     * 还有就是如果不小心把第一个位置和第二个位置搞反了，也会自动修正（例如想截取第4个和第2个字符之间的部分也是可以的哦~） 举个栗子
     */
    @Test
    public void test3(){
        String str = "abcdefgh";
        String strSub1 = StrUtil.sub(str, 2, 3); //strSub1 -> c
        Console.log(strSub1);
        String strSub2 = StrUtil.sub(str, 2, -3); //strSub2 -> cde
        Console.log(strSub2);
        String strSub3 = StrUtil.sub(str, 3, 2); //strSub2 ->
        Console.log(strSub3);

    }

    /**
     * str、bytes方法
     * 我承认把String.getByte(String charsetName)方法封装在这里了，原生的String.getByte()这个方法太坑了，
     * 使用系统编码，经常会有人跳进来导致乱码问题，所以我就加了这两个方法强制指定字符集了，包了个try抛出一个运行时异常，
     * 省的我得在我业务代码里处理那个恶心的UnsupportedEncodingException。
     */
    @Test
    public void test4(){
        String str = RandomUtil.randomString("鼠牛虎兔龙蛇马云猴鸡狗猪天下哈哈你个大西瓜",10);//随机字符串
        // str 方法
        Console.log(StrUtil.str(str, StandardCharsets.UTF_8));//将对象转为字符串
        Console.log(StrUtil.str(str.getBytes(), StandardCharsets.UTF_8));//解码字节码
        Console.log(StrUtil.str(str.getBytes(), "UTF-8"));//将Byte数组转为字符串
        Console.log(StrUtil.str(StrUtil.byteBuffer("sdfsdfxc", "UTF-8"), "UTF-8"));//将编码的byteBuffer数据转换为字符串
        // bytes 方法
        Console.log(StrUtil.bytes(str,StandardCharsets.UTF_8));
        Console.log(StrUtil.bytes(str));//编码 系统默认的字符集
    }

    /**
     *  format方法
     *  我会告诉你这是我最引以为豪的方法吗？灵感来自slf4j，可以使用字符串模板代替字符串拼接，
     *  我也自己实现了一个，而且变量的标识符都一样，神马叫无缝兼容~~来，上栗子（吃多了上火吧……）
     */
    @Test
    public void test5(){
        String template = "{}爱{}，就像老鼠爱大米";
        String template2 = "{a}爱{b}，就像老鼠爱大米";
        //参数我定义成了Object类型，如果传别的类型的也可以，会自动调用toString()方法的。
        String str = StrUtil.format(template, "我", "你"); //str -> 我爱你，就像老鼠爱大米
        System.out.println(str);
        HashMap<String, Object> map = new HashMap<>();
        map.put("a","牛");
        map.put("b",7);
        Console.log(StrUtil.format(template2, map));
    }

    /**
     * 其他常用方法
     */
    @Test
    public void test6(){
        /*
         *  填充字符串
         * 	fill(String str, char filledChar, int len, boolean isPre
         *  被填充字符，填充字符，填充长度，是否填充在前
         *   将已有字符串填充为规定长度，如果已有字符串超过这个长度则返回这个字符串
         */
        String baseStr = "史蒂芬森";
        Console.log(StrUtil.fill(baseStr, 'a', 7, false));
        Console.log(StrUtil.fillBefore(baseStr, 'a', 7));

        /**
         * 读取/写入 流
         */
        StringWriter writer = StrUtil.getWriter();//获取wirter输出流，可用于拼接字符串，并写入流
        StringReader reader = StrUtil.getReader("aaa");//获取reader输入流，可用于读取字符串

        /*读取字符串*/
        System.out.println(StrUtil.reverse(baseStr));

        /*计算两个字符串的相似度*/
        String baseStr1 = "芬芬钟秒了你";
        Console.log(StrUtil.similar(baseStr, baseStr1));//0.1666666667
        Console.log(StrUtil.similar(baseStr, baseStr1, 2));//16.67% 返回百分比 , scale 小数位 四舍五入

        /*将对象转为字符串*/
        Object obj = 5;
        System.out.println(StrUtil.utf8Str(obj));

        /*生成 uuid*/
        System.out.println(StrUtil.uuid());//a9b553d2-9e64-4f61-a507-fe392cab5bb0
    }


}
